package com.attendance.www.hr.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang.time.DateUtils;
import org.springframework.stereotype.Service;

import com.attendance.www.hr.beans.AttendanceBean;
import com.attendance.www.hr.constant.AppConstant;
import com.attendance.www.hr.dao.mapper.AccessInvalidLogsMapper;
import com.attendance.www.hr.dao.mapper.AttendanceMapper;
import com.attendance.www.hr.dao.mapper.CheckinoutMorningExtMapper;
import com.attendance.www.hr.dao.mapper.CheckinoutMorningMapper;
import com.attendance.www.hr.dao.mapper.EmployeeMapper;
import com.attendance.www.hr.dao.mapper.EmployeeSchedulMapper;
import com.attendance.www.hr.dao.mapper.NoEmployeeAttendanceExtMapper;
import com.attendance.www.hr.dao.mapper.NoEmployeeAttendanceMapper;
import com.attendance.www.hr.dao.mapper.PunchTimeMapper;
import com.attendance.www.hr.dao.mapper.SchedulDayMapper;
import com.attendance.www.hr.dao.mapper.SystemConfigureMapper;
import com.attendance.www.hr.entitys.AccessInvalidLogs;
import com.attendance.www.hr.entitys.Attendance;
import com.attendance.www.hr.entitys.AttendanceExample;
import com.attendance.www.hr.entitys.CheckinoutMorning;
import com.attendance.www.hr.entitys.Employee;
import com.attendance.www.hr.entitys.EmployeeExample;
import com.attendance.www.hr.entitys.EmployeeSchedul;
import com.attendance.www.hr.entitys.EmployeeSchedulExample;
import com.attendance.www.hr.entitys.NoEmployeeAttendance;
import com.attendance.www.hr.entitys.NoEmployeeAttendanceExt;
import com.attendance.www.hr.entitys.PunchTime;
import com.attendance.www.hr.entitys.PunchTimeExample;
import com.attendance.www.hr.entitys.SchedulDayExample;
import com.attendance.www.hr.entitys.SchedulDayKey;
import com.attendance.www.hr.entitys.SystemConfigure;
import com.attendance.www.hr.service.IAccessService;
import com.attendance.www.hr.service.IApprovalService;
import com.attendance.www.hr.service.IAttendanceService;
import com.attendance.www.hr.utils.AccessUtils;
import com.attendance.www.hr.utils.MailUtils;

@Service
public class AccessServiceImpl implements IAccessService {
	
	@Resource
	private EmployeeMapper employeeDao;
	@Resource
	private AttendanceMapper attendanceDao;
	@Resource
	private IAttendanceService attendanceService;
	@Resource
	private IApprovalService approvalService;
	@Resource
	private EmployeeSchedulMapper employeeSchedulDao;
	@Resource
	private PunchTimeMapper punchTimeDao;
	@Resource
	private SchedulDayMapper schedulDayDao;
	@Resource
	private NoEmployeeAttendanceMapper noEmployeeAttendanceDao;
	@Resource
	private AccessInvalidLogsMapper accessInvalidLogsDao;
	@Resource
	private NoEmployeeAttendanceExtMapper noEmployeeAttendanceExtDao;
	@Resource
	private SystemConfigureMapper systemConfigureDao;
	@Resource
	private CheckinoutMorningMapper checkinoutMorningDao;
	@Resource
	private CheckinoutMorningExtMapper checkinoutMorningExtDao;

	/**
	 * 自动保存考勤数据
	 */
	@Override
	public boolean saveAttendaceAuto() {
		//读取考勤数据
		List<CheckinoutMorning> cmList = AccessUtils.getAccessInfoMorning(AppConstant.ACCESS_ADDRESS1);
		Map<String, AttendanceBean> attMap=AccessUtils.getAccessInfo(AppConstant.ACCESS_ADDRESS1);
		//读取失败
		if (attMap.containsKey(AccessUtils.failedKey)) {
			//失效的地址
			String address=attMap.get(AccessUtils.failedKey).getAddress();
			String errorMessage=attMap.get(AccessUtils.failedKey).getErrorMessage();
			//查询初始化表
			SystemConfigure systemConfigure=systemConfigureDao.selectByPrimaryKey(1);
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
			String textPart = sdf.format(new Date()) + "，自动导入考勤失败，请管理员查明原因手动处理。";//正文
			//发Email
			boolean isSucceed = MailUtils.send(systemConfigure,systemConfigure.getMailReceive(), AppConstant.MAIL_TITLE, textPart, AppConstant.MAIL_ENDING);
			
			//记录失效日期，地址等数据
			AccessInvalidLogs ail=new AccessInvalidLogs();
			ail.setEmailInformation(textPart);
			if (isSucceed) {
				ail.setEmailState(1);// 
			} else {
				ail.setEmailState(0);// 失败0
			}
			ail.setInvalidLogsAddress(address);
			ail.setErrorMessage(errorMessage);
			ail.setInvalidLogsDate(new Date());
			accessInvalidLogsDao.insertSelective(ail);
			return false;
		}

		//保存考勤信息
		Calendar calStartDate = Calendar.getInstance();
		calStartDate.setTime(DateUtils.addDays(new Date(), -1));
		calStartDate.set(Calendar.HOUR_OF_DAY,0);
		calStartDate.set(Calendar.MINUTE,0);
		calStartDate.set(Calendar.SECOND,0);
		calStartDate.set(Calendar.MILLISECOND,0);
		Date attDate=calStartDate.getTime();//考勤日期
		//HR数据库中未录入的人员考勤信息（补漏）
		Map<String, Integer> neaMap=new HashMap<>();
		/*List<NoEmployeeAttendance> neaList = noEmployeeAttendanceDao.selectByExample(new NoEmployeeAttendanceExample());
		for (NoEmployeeAttendance noEmployeeAttendance : neaList) {
			  neaMap.put(noEmployeeAttendance.getNoEmployeeNo(), 1);
		}*/
		//HR数据库中未录入的人员考勤信息（补漏）
		List<NoEmployeeAttendanceExt> neaExtList=noEmployeeAttendanceExtDao.selectNoEmployeeAttendance();
		List<Integer> noEmployeeIdList=new ArrayList<Integer>();
		Date noEmployeeAttendanceDate=null;
		List<Attendance> attendanceNoList=null; 
		if(neaExtList.size()>0){
			//获取最小日期
			noEmployeeAttendanceDate=neaExtList.get(0).getNoEmployeeAttendanceDate(); 
			//处理人员ID集合
			for(int i=0;i<neaExtList.size();i++){
				boolean type=true;
				for(int j=0;j<noEmployeeIdList.size();j++){
					if(neaExtList.get(i).getEmployeeId().equals(noEmployeeIdList.get(j))){
						type=false;
						break;
					}
				}
				if(type){
					noEmployeeIdList.add(neaExtList.get(i).getEmployeeId());
				}
				neaMap.put(neaExtList.get(i).getNoEmployeeNo(), 1);
			}
			
			//查询考勤信息
			AttendanceExample attendanceExample=new AttendanceExample();
			attendanceExample.createCriteria()
			.andEmployeeIdIn(noEmployeeIdList)
			.andAttendanceDateBetween(noEmployeeAttendanceDate, attDate);
			attendanceNoList=attendanceDao.selectByExample(attendanceExample);
		}
	
		//查所有考勤日在职人员集合
		EmployeeExample employeeExample = new EmployeeExample();
		employeeExample.or().andEntryDateLessThanOrEqualTo(attDate).andEmployeeSeparatedDateIsNull();
		employeeExample.or().andEntryDateLessThanOrEqualTo(attDate).andEmployeeSeparatedDateGreaterThanOrEqualTo(attDate);
		List<Employee> empList=employeeDao.selectByExample(employeeExample);
		
		//在职人员Map
		Map<Integer, String> empMap=new HashMap<>();
		for (Employee employee : empList) {
			empMap.put(employee.getEmployeeId(), employee.getEmployeeNo());
		}
		//查询当日的已存在的考勤记录（由于一键补签生成的）
		AttendanceExample attendanceExample=new AttendanceExample();
		attendanceExample.createCriteria().andAttendanceDateEqualTo(attDate);
		List<Attendance> attendanceList=attendanceDao.selectByExample(attendanceExample);
		//已生产的考勤Map
		Map<String, Attendance> attendanceMap=new HashMap<>();
		for (Attendance attendance : attendanceList) {
			String employeeNo=empMap.get(attendance.getEmployeeId());
			attendanceMap.put(employeeNo, attendance);
		}
		
		List<Integer> employeeIdList=new ArrayList<>();
		Integer record=null;
		for (Employee employee : empList) {
			employeeIdList.add(employee.getEmployeeId());
			String employeeNo=employee.getEmployeeNo();
			AttendanceBean attendanceBean=attMap.get(employeeNo);
			if (attendanceBean!=null) {
				if (attendanceMap.get(employeeNo)==null) {
					Attendance attendance=new Attendance();
					attendance.setEmployeeId(employee.getEmployeeId());
					attendance.setAttendanceDate(attendanceBean.getAttendanceDate());
					attendance.setOriginalStartTime(attendanceBean.getStartTime());
					attendance.setStartTime(attendanceBean.getStartTime());
					attendance.setOriginalEndTime(attendanceBean.getEndTime());
					attendance.setEndTime(attendanceBean.getEndTime());
					attendance.setAddress(attendanceBean.getAddress());
					record=attendanceDao.insertSelective(attendance);
					if (record<=0) {
						return false;
					} else {
						attMap.remove(employeeNo);
					}
				} else {//已有考勤，更新考勤
					Attendance attendance=attendanceMap.get(employeeNo);
					attendance.setOriginalStartTime(attendanceBean.getStartTime());
					attendance.setStartTime(attendanceBean.getStartTime());
					attendance.setOriginalEndTime(attendanceBean.getEndTime());
					attendance.setEndTime(attendanceBean.getEndTime());
					attendance.setAddress(attendanceBean.getAddress());
					record=attendanceDao.updateByPrimaryKeySelective(attendance);
					if (record<=0) {
						return false;
					} else {
						attMap.remove(employeeNo);
					}
				}
			}
			//判断是否有未插入的考勤
			Integer neaValue = neaMap.get(employeeNo);
			if (neaValue != null) {
				for (NoEmployeeAttendanceExt nea : neaExtList) {
					if (nea.getNoEmployeeNo().equals(employeeNo)) {
						Integer attendanceId=null;
						//查询考勤记录是否存在
						for(int io=0;io<attendanceNoList.size();io++){
							//判断人员ID和日期是否相同
							Attendance attendance=attendanceNoList.get(io);
							if(attendance.getEmployeeId().equals(nea.getEmployeeId())
									&& attendance.getAttendanceDate().equals(nea.getNoEmployeeAttendanceDate())){
								attendanceId=attendance.getAttendanceId();
								break;
							}
						}
						//新增
						if(attendanceId==null){
							Attendance attendance=new Attendance();
							attendance.setEmployeeId(nea.getEmployeeId());
							attendance.setAttendanceDate(nea.getNoEmployeeAttendanceDate());
							attendance.setOriginalStartTime(nea.getOriginalStartTime());
							attendance.setStartTime(nea.getOriginalStartTime());
							attendance.setOriginalEndTime(nea.getOriginalEndTime());
							attendance.setEndTime(nea.getOriginalEndTime());
							attendance.setAddress(nea.getAddress());
							int record2=attendanceDao.insertSelective(attendance);
							if (record2<=0) {
								return false;
							} else {//插入成功，删除数据
								noEmployeeAttendanceDao.deleteByPrimaryKey(nea.getNoEmployeeAttendanceId());
							}
						}
						//修改
						else{
							Attendance attendance=new Attendance();
							attendance.setAttendanceId(attendanceId);
							attendance.setEmployeeId(nea.getEmployeeId());
							attendance.setAttendanceDate(nea.getNoEmployeeAttendanceDate());
							attendance.setOriginalStartTime(nea.getOriginalStartTime());
							attendance.setStartTime(nea.getOriginalStartTime());
							attendance.setOriginalEndTime(nea.getOriginalEndTime());
							attendance.setEndTime(nea.getOriginalEndTime());
							attendance.setAddress(nea.getAddress());
							attendance.setUpdateTime(new Date());
							int record2=attendanceDao.updateByPrimaryKeySelective(attendance);
							if (record2<=0) {
								return false;
							} else {//插入成功，删除数据
								noEmployeeAttendanceDao.deleteByPrimaryKey(nea.getNoEmployeeAttendanceId());
							}
						}
					}
				}
			}
		}
		
		//保存未在HR数据库中新增的（刚入职）人员的考勤信息
		Set<String> employeeNoKey = attMap.keySet();
		Iterator<String> iter = employeeNoKey.iterator();
		while (iter.hasNext()) {
			String key = iter.next();
			AttendanceBean attendanceBean=attMap.get(key);
			NoEmployeeAttendance nea = new NoEmployeeAttendance();
			nea.setNoEmployeeNo(attendanceBean.getEmployeeNo());
			nea.setNoEmployeeAttendanceDate(attendanceBean.getAttendanceDate());
			nea.setOriginalStartTime(attendanceBean.getStartTime());
			nea.setOriginalEndTime(attendanceBean.getEndTime());
			nea.setAddress(attendanceBean.getAddress());
			noEmployeeAttendanceDao.insertSelective(nea);
		}
		
		//考勤日期
		Map<Date, Date> attendanceDateMap=new HashMap<>();
		attendanceDateMap.put(attDate, attDate);
		
		// 查询班次情况
		EmployeeSchedulExample employeeSchedulExample = new EmployeeSchedulExample();
		employeeSchedulExample.setOrderByClause("employee_id asc,from_date desc");
		List<EmployeeSchedul> employeeSchedulList = employeeSchedulDao.selectByExample(employeeSchedulExample);
		List<Integer> swIdList = new ArrayList<Integer>();
		Map<Integer, List<EmployeeSchedul>> employeeSchedulMap = new HashMap<Integer, List<EmployeeSchedul>>();
		for (int ei = 0; ei < employeeSchedulList.size(); ei++) {
			if (employeeSchedulMap.containsKey(employeeSchedulList.get(ei).getEmployeeId())) {
				List<EmployeeSchedul> eList = employeeSchedulMap.get(employeeSchedulList.get(ei).getEmployeeId());
				eList.add(employeeSchedulList.get(ei));
				employeeSchedulMap.put(employeeSchedulList.get(ei).getEmployeeId(), eList);
			} else {
				List<EmployeeSchedul> eList = new ArrayList<EmployeeSchedul>();
				eList.add(employeeSchedulList.get(ei));
				employeeSchedulMap.put(employeeSchedulList.get(ei).getEmployeeId(), eList);
			}
			swIdList.add(employeeSchedulList.get(ei).getSwId());
		}
		// 查询考勤打卡
		List<PunchTime> punchTimeList = punchTimeDao.selectByExample(new PunchTimeExample());
		Map<Integer, PunchTime> punchTimeMap = new HashMap<Integer, PunchTime>();
		for (int pi = 0; pi < punchTimeList.size(); pi++) {
			punchTimeMap.put(punchTimeList.get(pi).getPunchTimeId(), punchTimeList.get(pi));
		}
		// 查询班次日期
		SchedulDayExample schedulDayExample = new SchedulDayExample();
		schedulDayExample.createCriteria()
		.andSwIdIn(swIdList);
		List<SchedulDayKey> schedulDayKeyList = schedulDayDao.selectByExample(schedulDayExample);
		Map<Integer, List<SchedulDayKey>> schedulDayKeyMap = new HashMap<Integer, List<SchedulDayKey>>();
		for (int si = 0; si < schedulDayKeyList.size(); si++) {
			if (schedulDayKeyMap.containsKey(schedulDayKeyList.get(si).getSwId())) {
				List<SchedulDayKey> lList = schedulDayKeyMap.get(schedulDayKeyList.get(si).getSwId());
				lList.add(schedulDayKeyList.get(si));
				schedulDayKeyMap.put(schedulDayKeyList.get(si).getSwId(), lList);
			} else {
				List<SchedulDayKey> lList = new ArrayList<SchedulDayKey>();
				lList.add(schedulDayKeyList.get(si));
				schedulDayKeyMap.put(schedulDayKeyList.get(si).getSwId(), lList);
			}
		}
		
		//生成旷工人员考勤信息
		attendanceService.addNotAttendanceDate(attendanceDateMap, employeeIdList, employeeSchedulMap, schedulDayKeyMap, punchTimeMap);
		//重计算
		approvalService.resetAttendance(attDate, DateUtils.addDays(attDate, 1), employeeIdList);
		//判断未导入成功员工的日期是否不为空，重新计算他们的考勤
		if(noEmployeeAttendanceDate!=null){
			if(noEmployeeIdList.size()>0){
				approvalService.resetAttendance(noEmployeeAttendanceDate,attDate, noEmployeeIdList);
			}
		}
		//保存早上打卡信息 TODO
		for (CheckinoutMorning checkinoutMorning : cmList) {
			checkinoutMorningDao.insertSelective(checkinoutMorning);
		}
		//删除多次导入产生的重复数据
		record=checkinoutMorningExtDao.deleteDuplicatedData();
		return true;
	}

	
	public static boolean sameDate(Date d1, Date d2) {  
	    if(null == d1 || null == d2)  
	        return false;  
	    Calendar cal1 = Calendar.getInstance();  
	    cal1.setTime(d1);  
	    cal1.set(Calendar.HOUR_OF_DAY, 0);  
	    cal1.set(Calendar.MINUTE, 0);  
	    cal1.set(Calendar.SECOND, 0);  
	    cal1.set(Calendar.MILLISECOND, 0);  
	    Calendar cal2 = Calendar.getInstance();  
	    cal2.setTime(d2);  
	    cal2.set(Calendar.HOUR_OF_DAY, 0);  
	    cal2.set(Calendar.MINUTE, 0);  
	    cal2.set(Calendar.SECOND, 0);  
	    cal2.set(Calendar.MILLISECOND, 0);  
	    return  cal1.getTime().equals(cal2.getTime());  
	} 
}
